//********************************************************************
// 
//  file:  FormUpload.cs
// 
//  (C) Copyright 2010, Diomede Corporation
//  All rights reserved
// 
//  Use, modification, and distribution is subject to   
//  the New BSD License (See accompanying file license.txt).
// 
//********************************************************************

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using data.diomedestorage.com;

namespace Diomede.SDK.UI
{
    public partial class FormUpload : Form
    {
        IFileManagement fileManagement;
        MetaData metaData;

        public FormUpload()
        {
            InitializeComponent();
        }

        public FormUpload(MetaData md)
        {
            InitializeComponent();
            metaData = md;
        }

        #region Single Upload

        private void btnOpenFile_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Multiselect = false;
            DialogResult res = dlg.ShowDialog(this);
            if (res == DialogResult.OK)
            {
                txtFileToUpload.Text = dlg.FileName;
            }
        }
        Thread th;
        private void btnSingleUpload_Click(object sender, EventArgs e)
        {
            if (btnSingleUpload.Text == "Stop")
            {
                th.Abort();
                this.Close();
                return;
            }
            pbSingle.Value = 0;
            if (string.IsNullOrEmpty(txtFileToUpload.Text) || !File.Exists(txtFileToUpload.Text))
            {
                MessageBox.Show(this, "Invalid file to upload.", "Upload", MessageBoxButtons.OK);
                return;
            }
            btnGetUploadtoken.Enabled = false;

            btnSingleUpload.Text = "Stop";
            btnSingleUpload.Refresh();
            th = new Thread(new ThreadStart(uploadSingle));
            th.Start();

            //uploadSingle();
        }


        void uploadSingle()
        {
            if (fileManagement == null)
            {
                registerEvents();
            }
            //fileManagement.Upload(txtFileToUpload.Text, Diomede.SDK.Enums.StorageInfo.OnlineStorage);
            //use fileid for checking file upload

            throw new NotImplementedException();

            //IFileManagementExecResult uploadResult = fileManagement.Upload(new FileInfo(txtFileToUpload.Text), string.Empty, string.Empty, null);
            //if (uploadResult.Status != Diomede.SDK.Enums.ExecutionResults.Success)
            //{
            //    MessageBox.Show(uploadResult.Message, "Upload Error");
            //}
            //else
            //{
            //    setMetaData(uploadResult.StoredFiles);
            //}
        }

        void setMetaData(List<IStoredFile> files)
        {
            if (metaData != null)
            {

                foreach (IStoredFile file in files)
                { 
                    //metadata is already in the service
                    if (metaData.metaDataID > 0)
                    {
                        file.AddMetaData(metaData.metaDataID);
                    }
                    else
                    {
                        IAddMetaDataExecResult r = file.AddMetaData(metaData.name, metaData.value);
                        metaData.metaDataID = r.MetaDataID;
                    }

                }
            }
        }

        private void registerEvents()
        {
            fileManagement = session as IFileManagement;
            fileManagement.OnFileUploadProgress += new EventHandler<FileUploadProgressArgs>(fileManagement_OnFileUploadProgress);
            fileManagement.OnNewMessage += new EventHandler<FileUploadMessageArgs>(fileManagement_OnNewMessage);
            fileManagement.OnUploadComplete += new EventHandler<FileUploadMessageArgs>(fileManagement_OnUploadComplete);
            fileManagement.OnUploadError += new EventHandler<FileUploadMessageArgs>(fileManagement_OnUploadError);
            fileManagement.OnUploadStopped += new EventHandler<FileUploadMessageArgs>(fileManagement_OnUploadStopped);
            if (activeTab == 1)
            {
                fileManagement.OnTotalUploadProgress += new EventHandler<TotalUploadProgressArgs>(fileManagement_OnTotalUploadProgress);
                fileManagement.OnTotalUploadComplete += new EventHandler<FileUploadMessageArgs>(fileManagement_OnTotalUploadComplete);
            }
        }

        string messageInvoked;
        void writeProgress()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(writeProgress));
            }
            else
            {
                if (activeTab == 0)
                {
                    lblSingleProgress.Text = messageInvoked;
                    lblSingleProgress.Refresh();
                }
                else
                {
                    lblFileProgress.Text = messageInvoked;
                    lblFileProgress.Refresh();
                }
            }
        }


        void fileManagement_OnTotalUploadComplete(object sender, FileUploadMessageArgs e)
        {
            totalProgressMessage = e.Message;
            writeTotalProgress();
            
        }

        void fileManagement_OnTotalUploadProgress(object sender, TotalUploadProgressArgs e)
        {
            fileCount = e.Count;
            fileUploaded = e.Uploaded;
            totalProgressMessage = string.Format("Upload progress... {0} / {1}", fileUploaded, fileCount);
            writeTotalProgress();
        }

        void fileManagement_OnNewMessage(object sender, FileUploadMessageArgs e)
        {
            messageInvoked = e.Message;
            writeProgress();
        }

        void fileManagement_OnUploadError(object sender, FileUploadMessageArgs e)
        {
            //throw new Exception("The method or operation is not implemented.");
        }

        void fileManagement_OnUploadStopped(object sender, FileUploadMessageArgs e)
        {
            //throw new Exception("The method or operation is not implemented.");
        }

        void fileManagement_OnUploadComplete(object sender, FileUploadMessageArgs e)
        {
            messageInvoked = e.Message;
            writeProgress();
            
        }

        

        void changeButton()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(changeButton));
            }
            else
            {
                if (activeTab == 0)
                    btnSingleUpload.Text = "Upload";
                else
                    btnFolderUpload.Text = "Upload";
            }
        }

        string totalProgressMessage;
        long fileUploaded, fileCount;
        void writeTotalProgress()
        {
            if (this.InvokeRequired)
                this.Invoke(new MethodInvoker(writeTotalProgress));
            else
            {
                if (activeTab == 1)
                {
                    pbFolder.Maximum = 100;
                    pbFolder.Value = (int)(((double)fileUploaded) / ((double)fileCount) * 100);
                    pbFolder.Refresh();
                    lblFolderProgress.Text = totalProgressMessage;
                    lblFolderProgress.Refresh();
                    if (pbFolder.Value == pbFolder.Maximum)
                    {
                        btnFolderUpload.Text = "Upload";
                        
                    }
                }
                
            }
        }

        long valueInvoked, lengthInvoked;

        void writeProgressbar()
        {
            if (this.InvokeRequired)
                this.Invoke(new MethodInvoker(writeProgressbar));
            else
            {
                if (activeTab == 0)
                {
                    pbSingle.Maximum = 100;
                    pbSingle.Value = (int)(((double)valueInvoked) / ((double)lengthInvoked) * 100);
                    pbSingle.Refresh();
                    if (pbSingle.Value == pbSingle.Maximum)
                    {
                        btnSingleUpload.Text = "Upload";
                        this.Close();
                    }
                }
                else
                {
                    pbFile.Maximum = 100;
                    pbFile.Value = (int)(((double)valueInvoked) / ((double)lengthInvoked) * 100);
                    if (pbFile.Value == pbFile.Maximum)
                        lblFileProgress.Text = "Done.";
                    pbFile.Refresh();
                }
            }
        }

        void fileManagement_OnFileUploadProgress(object sender, FileUploadProgressArgs e)
        {
            messageInvoked = e.ToPercentString();
            writeProgress();
            valueInvoked = e.BytesRead;
            lengthInvoked = e.Length;
            writeProgressbar();
        }

        private ISession session;

        public ISession Session
        {
            get { return session; }
            set { session = value; }
        }

        #endregion



        #region Folder Upload

        private void btnOpenFolder_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dlg = new FolderBrowserDialog();

            DialogResult res = dlg.ShowDialog(this);
            if (res == DialogResult.OK)
            {
                txtFolderToUpload.Text = dlg.SelectedPath;
            }
        }

        string targetDirectory = "";
        Thread thFolder;
        delegate void StringParameterDelegate(string value);

        private void btnFolderUpload_Click(object sender, EventArgs e)
        {
            targetDirectory = txtFolderToUpload.Text;
            if (btnFolderUpload.Text == "Stop")
            {
                thFolder.Abort();
                this.Close();
                return;
            }
            pbFolder.Value = 0;

            if (string.IsNullOrEmpty(targetDirectory) || !Directory.Exists(targetDirectory))
            {
                MessageBox.Show(this, "Invalid folder to upload.", "Upload", MessageBoxButtons.OK);
                return;
            }
            btnFolderUpload.Text = "Stop";
            btnFolderUpload.Refresh();
            thFolder = new Thread(new ThreadStart(uploadFolder));
            thFolder.Start();

            //uploadFolder();
        }

        void uploadFolder()
        {
            if (fileManagement == null)
            {
                registerEvents();
            }

            processDirectory(targetDirectory);
        }



        void processDirectory(string targetDirectory)
        {
            // Process the list of files found in the directory.
            string[] fileEntries = Directory.GetFiles(targetDirectory);

            if (fileEntries.Length > 0)
            {
                throw new NotImplementedException();

                //IFileManagementBulkUploadExecResult result = fileManagement.Upload(filterFiles(fileEntries), Diomede.SDK.Enums.StorageInfo.OnlineStorage); ;
                //foreach (IFileManagementExecResult item in result.UploadResults)
                //{
                //    if (item.Status == Diomede.SDK.Enums.ExecutionResults.Success)
                //    {
                //        setMetaData(item.StoredFiles);
                //    }
                //}
            }
            // Recurse into subdirectories of this directory.
            if (chkSubFolder.Checked)
            {
                string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
                foreach (string subdirectory in subdirectoryEntries)
                    processDirectory(subdirectory);
            }
        }

        //excludes files with .md5 extensions.
        private static string[] filterFiles(string[] fileEntries)
        {
            List<string> filteredEntries = new List<string>();

            foreach (string f in fileEntries)
            {
                if (!f.EndsWith(".md5"))
                {
                    filteredEntries.Add(f);
                }
            }

            return filteredEntries.ToArray();
        }


        #endregion

        int activeTab = 0;
        private void tabMain_SelectedIndexChanged(object sender, EventArgs e)
        {
            activeTab = tabMain.SelectedIndex;
        }

        private void btnGetUploadtoken_Click(object sender, EventArgs e)
        {
            pbSingle.Value = 0;
            if (string.IsNullOrEmpty(txtFileToUpload.Text) || !File.Exists(txtFileToUpload.Text))
            {
                MessageBox.Show(this, "Invalid file to upload.", "Upload", MessageBoxButtons.OK);
                return;
            }
            IFileManagement fm = session as IFileManagement;
            IGetUploadTokenExecResult result = fm.GetUploadToken(txtFileToUpload.Text, string.Empty);
            if (result.Status == Diomede.SDK.Enums.ExecutionResults.Success)
            {
                MessageBox.Show(this, result.UploadToken, "Get Upload Token");
            }
            else
            {
                MessageBox.Show(this, result.Message, "Failed To Get Upload Token");
            }
        }

       



    }
}